package messagepasser;

/**
 * 
 * @author Rishit Shroff(rshroff)
 * @author Huimin Yang(huiminy)
 * @description Contains the description of the TimeShapedMessage class 
 */

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.Timer;

public class TimeStampedMessage extends Message implements Serializable, Comparable{

	private ClockService stamp;

	protected Map<String, Boolean> ackList = new HashMap<String, Boolean>();
	private Map<String, Integer> sequenceNumber = new HashMap<String, Integer>();
	protected boolean timer = false;
	private ClockService senderStamp = null; //not null only when type == "recv"
	private int seqNo = -1;
	private String orgSender;
	
	public String getOrgSender() {
		return orgSender;
	}
	public void setOrgSender(String orgSender) {
		this.orgSender = orgSender;
	}
	public int getSeqNo() {
		return seqNo;
	}
	public void setSeqNo(int seqNo) {
		this.seqNo = seqNo;
	}
	public Map<String, Boolean> getAckList() {
		return ackList;
	}
	public void setAckList(Map<String, Boolean> ackList) {
		this.ackList = ackList;
	}
	public Map<String, Integer> getSequenceNumber() {
		return sequenceNumber;
	}
	public void setSequenceNumber(Map<String, Integer> sequenceNumber) {
		this.sequenceNumber = sequenceNumber;
	}
	public boolean isTimer() {
		return timer;
	}
	public void setTimer(boolean timer) {
		this.timer = timer;
	}
	public void setStamp(ClockService stamp) {
		this.stamp = stamp;
	}
	public TimeStampedMessage(String dest, String src, String msg_class, String id, Object data) {
		super(dest, src, msg_class, id, data);
	}
	public TimeStampedMessage(String dest, String src, String msg_class, String id, Object data, boolean log, boolean multi) {
		super(dest, src, msg_class, id, data, log, multi);
	}
	
	
	public TimeStampedMessage(Header header, Object data) {
		super(header, data);
	}
	
	
	public void attatchStamp(ClockService clock) {
		this.stamp = clock;
	}
	
	public ClockService getStamp() {
		return this.stamp;
	}
	
	
	public void setSenderStamp(ClockService senderStamp) {
		this.senderStamp = senderStamp;
	}
	
	public ClockService getSenderStamp() {
		return this.senderStamp;
	}
	
	public void setDest(String dest) {
		header.setDest(dest);
	}
	
	public TimeStampedMessage serializeFor(String dest) {
		TimeStampedMessage serializedMsg = 
			new TimeStampedMessage (
					dest, 
					super.header.getSrc(), 
					super.header.getMsgClass(), 
					super.header.getID(), 
					super.getPayload(), 
					super.isloggable, 
					super.multicastMsg);
		serializedMsg.attatchStamp((Vector)stamp.clone());
		serializedMsg.setSenderStamp((Vector)senderStamp.clone());
		serializedMsg.setMsgType(this.getMsgType());
		serializedMsg.sequenceNumber = (this.sequenceNumber);
		serializedMsg.seqNo = this.seqNo;
		serializedMsg.orgSender = this.orgSender;
		return serializedMsg;
	}
	/**
	 * check whether the message to this destination has received an ack response
	 * 
	 * @param destination
	 * @return true if received an ack from the destination
	 */
	public boolean checkSuccess(String destination) {
		return ackList.get(destination);
	}
	
	/**
	 * 
	 * @return true if the message is acked by every multicast destination
	 */
	public boolean allAcked() {
		
		for (String dest : this.getAckList().keySet()) {
			if (ackList== null) {
				System.out.println("ackList is null");
			} else {
				System.out.println("checking dest " + dest + " " + ackList.get(dest));
				
				if (ackList.get(dest) == false) {
					return false;
				}
			}
		}
		return true;
	}
	
	public void initializeAckList() {
		ackList = new HashMap<String, Boolean>();
		String[] destination = this.getMultiDestination();
		for (String dest : destination) {
			ackList.put(dest, false);
		}
	}
	
	public int compareTo(Object arg0) {
		
		//XXX : Not implement for logical
	
		TimeStampedMessage m = (TimeStampedMessage)arg0;
		
		int greater = 0, smaller = 0;
		List<Integer> clock = ((Vector)this.getSenderStamp()).getClock();
		List<Integer> myClock = ((Vector)m.getSenderStamp()).getClock();
		for (int i = 0; i < clock.size(); i++) {
			if(myClock.get(i) > clock.get(i)) {
				greater++;
			}
			else if(myClock.get(i) < clock.get(i)) {
				smaller++;
			}
		}
		if(smaller > 0 && greater > 0) {
			return 0;
		}
		else if (smaller > 0){
			return 1;
		}
		else {
			return -1;
		}
		// TODO Auto-generated method stub
		
	}
	
	public void initAckList(String[] nodeNames) {
		if (ackList.isEmpty()) {
			for (String node: nodeNames){
				ackList.put(node, new Boolean("false"));
			}
		}
	}
	
}
